package com.ruicar.afs.cloud.common.mq.rabbit.proxy;

import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.spring.proxy.interfaces.AfsInterfaceProxy;
import com.ruicar.afs.cloud.common.core.util.SpringContextHolder;
import com.ruicar.afs.cloud.common.mq.rabbit.anno.send.AfsRabbitMqSender;
import com.ruicar.afs.cloud.common.mq.rabbit.constant.AfsRabbitMqConstants;
import com.ruicar.afs.cloud.common.mq.rabbit.helper.CacheInfo;
import com.ruicar.afs.cloud.common.mq.rabbit.message.AfsTransEntity;
import com.ruicar.afs.cloud.common.mq.rabbit.message.RabbitMessageWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Slf4j(topic = "mq-message-send")
public class AfsMqClientInterfaceProxy extends AfsInterfaceProxy {
    private Map<Method, RabbitMqTarget> mqTargetMap;

    @Override
    public void processDefine(Class<?> clazz) {
        mqTargetMap = new HashMap<>();
        Method[] methods = ReflectUtil.getMethods(clazz);
        for (Method method : methods) {
            AfsRabbitMqSender rabbitSender = AnnotationUtils.findAnnotation(method, AfsRabbitMqSender.class);
            if (rabbitSender != null) {
                mqTargetMap.put(method, RabbitMqTarget.builder().afsMessage(rabbitSender.afsMessage()).enAble(rabbitSender.enableOn()).exchange(rabbitSender.exchangeName()).serverAlias(rabbitSender.serverAlias()).queue(rabbitSender.queueName()).build());
            }
        }
    }

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        Assert.isTrue(objects != null, "发送消息不能为空");
        Assert.isTrue(objects.length == 1, "只能发送单个对象消息");
        Assert.isTrue(mqTargetMap.containsKey(method), "未定义的请求方法");
        RabbitMqTarget mqTarget = mqTargetMap.get(method);
        if(!StringUtils.isEmpty(mqTarget.getEnAble())&&!SpringContextHolder.getApplicationContext().getEnvironment().containsProperty(mqTarget.getEnAble().replace("${", "").replace("}", ""))){
            throw new AfsBaseException(MessageFormat.format("{0}-{1}-{2}-未开启,开启条件{3}",mqTarget.getServerAlias(),mqTarget.getExchange(),mqTarget.getQueue(),mqTarget.getEnAble()));
        }
        String serverAlias = mqTarget.getServerAlias();
        String queueName = mqTarget.getQueue();
        String exchangeName = mqTarget.getExchange();

        if (exchangeName.startsWith("${")) {
            exchangeName = SpringContextHolder.getApplicationContext().getEnvironment().getProperty(exchangeName.replace("${", "").replace("}", ""));
        }
        if (serverAlias.startsWith("${")) {
            serverAlias = SpringContextHolder.getApplicationContext().getEnvironment().getProperty(serverAlias.replace("${", "").replace("}", ""));
        }
        if (queueName.startsWith("${")) {
            queueName = SpringContextHolder.getApplicationContext().getEnvironment().getProperty(queueName.replace("${", "").replace("}", ""));
        }


        Assert.isTrue(CacheInfo.CACHE_SERVER_TEMPLATE.containsKey(serverAlias), "别名为[" + serverAlias + "]MQ 服务未定义");
        if(mqTarget.isAfsMessage()) {
            RabbitMessageWrapper rabbitMessageWrapper = new RabbitMessageWrapper();
            rabbitMessageWrapper.setTag(AfsRabbitMqConstants.AFS_TAG + "_send_by_AfsInterfaceProxy");
            rabbitMessageWrapper.setAfsMessageId(UUID.randomUUID().toString().replaceAll("-", ""));
            if (objects[0] instanceof AfsTransEntity) {
                rabbitMessageWrapper.setAfsEntity(Boolean.TRUE);
                rabbitMessageWrapper.setTransCode(((AfsTransEntity) (objects[0])).getTransCode());
            } else {
                rabbitMessageWrapper.setAfsEntity(Boolean.FALSE);
            }
            rabbitMessageWrapper.setContent(JSONObject.toJSONString(objects[0]));
            log.info("发送mq消息,交换名:[{}],队列名:[{}],消息内容:\n[{}]", exchangeName, queueName, rabbitMessageWrapper.getContent());
            CacheInfo.CACHE_SERVER_TEMPLATE
                    .get(serverAlias)
                    .getRabbitTemplate()
                    .convertAndSend(exchangeName, queueName, JSONObject.toJSONString(rabbitMessageWrapper));
        }else {
            //非afs平台内部 消息直接发送原始格式（String类型）
            Assert.isTrue(objects[0] instanceof String,"非afs内部交易消息，消息内容必须为String格式");
            log.info("发送mq消息,交换名:[{}],队列名:[{}],消息内容:\n[{}]", exchangeName, queueName, objects[0]);
            CacheInfo.CACHE_SERVER_TEMPLATE
                    .get(serverAlias)
                    .getRabbitTemplate()
                    .convertAndSend(exchangeName, queueName,objects[0]);
        }
        return null;
    }
}
